#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FastAPI 学习项目主应用程序

这是一个完整的 FastAPI 学习项目，包含以下功能：
1. 用户认证和授权
2. 用户管理
3. 物品管理
4. 数据库操作（CRUD）
5. 中间件（日志、错误处理、性能监控、安全、限流）
6. API 文档
7. 安全最佳实践

项目结构：
- app/: 应用程序包
  - models/: 数据模型
  - routers/: API 路由
  - database/: 数据库相关
  - utils/: 工具函数
  - middleware/: 中间件
- main.py: 主应用程序文件
- requirements.txt: 依赖包列表
- README.md: 项目文档

作者: FastAPI 学习项目
创建时间: 2024
"""

import uvicorn
from fastapi import FastAPI, Request, Depends
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from fastapi.responses import JSONResponse
from contextlib import asynccontextmanager
from loguru import logger
import sys
from pathlib import Path

# 添加项目根目录到 Python 路径
project_root = Path(__file__).parent
sys.path.insert(0, str(project_root))

# 导入应用程序组件
from app.database import init_db, get_db_info, check_db_connection
from app.routers import auth, users, items
from app.middleware.logging import LoggingMiddleware
from app.middleware.error_handler import ErrorHandlerMiddleware
from app.middleware.performance import PerformanceMiddleware
from app.middleware.security import SecurityMiddleware, SecurityConfig
from app.middleware.rate_limit import (
    RateLimitMiddleware, 
    RateLimitRule, 
    RateLimitStrategy
)
from app.utils.security import get_current_user


@asynccontextmanager
async def lifespan(app: FastAPI):
    """
    应用程序生命周期管理
    
    在应用启动时初始化数据库，在关闭时清理资源。
    
    Args:
        app: FastAPI 应用实例
    """
    # 启动时执行
    logger.info("🚀 FastAPI 学习项目启动中...")
    
    try:
        # 初始化数据库
        logger.info("📊 初始化数据库...")
        await init_db()
        
        # 检查数据库连接
        if await check_db_connection():
            logger.success("✅ 数据库连接成功")
            db_info = await get_db_info()
            logger.info(f"📋 数据库信息: {db_info}")
        else:
            logger.error("❌ 数据库连接失败")
        
        logger.success("🎉 应用程序启动完成")
        
    except Exception as e:
        logger.error(f"❌ 应用程序启动失败: {e}")
        raise
    
    yield
    
    # 关闭时执行
    logger.info("🛑 FastAPI 学习项目关闭中...")
    logger.info("👋 再见！")


# 创建 FastAPI 应用实例
app = FastAPI(
    title="FastAPI 学习项目",
    description="""
    这是一个完整的 FastAPI 学习项目，展示了现代 Web API 开发的最佳实践。
    
    ## 主要功能
    
    * **用户管理**: 用户注册、登录、信息管理
    * **认证授权**: JWT 令牌认证、权限控制
    * **物品管理**: CRUD 操作、搜索、分类
    * **安全防护**: 限流、安全头部、输入验证
    * **性能监控**: 请求追踪、性能分析
    * **错误处理**: 统一错误响应、日志记录
    
    ## 技术栈
    
    * **FastAPI**: 现代、快速的 Web 框架
    * **SQLAlchemy**: Python SQL 工具包和 ORM
    * **Pydantic**: 数据验证和设置管理
    * **JWT**: JSON Web Token 认证
    * **bcrypt**: 密码哈希
    * **Loguru**: 现代日志库
    
    ## API 文档
    
    * **Swagger UI**: `/docs`
    * **ReDoc**: `/redoc`
    
    ## 开发者信息
    
    这个项目是为了学习 FastAPI 和现代 Web 开发技术而创建的。
    包含了生产环境中常用的功能和最佳实践。
    """,
    version="1.0.0",
    contact={
        "name": "FastAPI 学习项目",
        "email": "example@example.com",
    },
    license_info={
        "name": "MIT",
        "url": "https://opensource.org/licenses/MIT",
    },
    lifespan=lifespan,
    docs_url="/docs",
    redoc_url="/redoc",
    openapi_url="/openapi.json"
)


# 配置 CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "http://localhost:3000",  # React 开发服务器
        "http://localhost:8080",  # Vue 开发服务器
        "http://127.0.0.1:3000",
        "http://127.0.0.1:8080",
    ],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
    allow_headers=["*"],
)


# 配置受信任主机
app.add_middleware(
    TrustedHostMiddleware,
    allowed_hosts=[
        "localhost",
        "127.0.0.1",
        "*.localhost",
        "*.127.0.0.1",
    ]
)


# 添加自定义中间件
# 注意：中间件的添加顺序很重要，后添加的先执行

# 1. 限流中间件（最外层）
rate_limit_rules = {
    "/api/auth/login": RateLimitRule(
        requests=5,  # 每分钟最多5次登录尝试
        window=60,
        strategy=RateLimitStrategy.SLIDING_WINDOW
    ),
    "/api/auth/register": RateLimitRule(
        requests=3,  # 每小时最多3次注册
        window=3600,
        strategy=RateLimitStrategy.SLIDING_WINDOW
    ),
    "/api/": RateLimitRule(
        requests=1000,  # API 路径每分钟1000次请求
        window=60,
        strategy=RateLimitStrategy.SLIDING_WINDOW
    )
}

app.add_middleware(
    RateLimitMiddleware,
    default_rule=RateLimitRule(
        requests=100,  # 默认每分钟100次请求
        window=60,
        strategy=RateLimitStrategy.SLIDING_WINDOW
    ),
    rules=rate_limit_rules
)

# 2. 安全中间件
security_config = SecurityConfig(
    enable_security_headers=True,
    enable_sql_injection_check=True,
    enable_xss_check=True,
    enable_path_traversal_check=True,
    max_request_size=10 * 1024 * 1024,  # 10MB
    block_suspicious_user_agents=True
)

app.add_middleware(SecurityMiddleware, config=security_config)

# 3. 性能监控中间件
app.add_middleware(
    PerformanceMiddleware,
    slow_request_threshold=1.0,  # 1秒为慢请求
    memory_threshold=80.0,  # 80% 内存使用率告警
    cpu_threshold=80.0,  # 80% CPU 使用率告警
    enable_detailed_logging=True
)

# 4. 错误处理中间件
app.add_middleware(ErrorHandlerMiddleware)

# 5. 日志中间件（最内层，记录所有请求）
app.add_middleware(
    LoggingMiddleware,
    exclude_paths=["/health", "/metrics", "/favicon.ico"],
    log_request_body=False,  # 生产环境建议关闭
    log_response_body=False  # 生产环境建议关闭
)


# 注册路由
app.include_router(
    auth.router,
    prefix="/api/auth",
    tags=["认证"],
    responses={
        401: {"description": "未授权"},
        403: {"description": "禁止访问"},
        422: {"description": "验证错误"}
    }
)

app.include_router(
    users.router,
    prefix="/api/users",
    tags=["用户管理"],
    dependencies=[Depends(get_current_user)],  # 需要认证
    responses={
        401: {"description": "未授权"},
        403: {"description": "禁止访问"},
        404: {"description": "用户不存在"},
        422: {"description": "验证错误"}
    }
)

app.include_router(
    items.router,
    prefix="/api/items",
    tags=["物品管理"],
    responses={
        401: {"description": "未授权"},
        403: {"description": "禁止访问"},
        404: {"description": "物品不存在"},
        422: {"description": "验证错误"}
    }
)


# 根路径
@app.get(
    "/",
    summary="欢迎页面",
    description="返回 API 欢迎信息和基本状态",
    response_description="欢迎信息",
    tags=["基础"]
)
async def root():
    """
    API 根路径，返回欢迎信息
    
    Returns:
        dict: 包含欢迎信息和 API 状态的字典
    """
    return {
        "message": "欢迎使用 FastAPI 学习项目！",
        "description": "这是一个完整的 FastAPI 学习项目，展示了现代 Web API 开发的最佳实践。",
        "version": "1.0.0",
        "docs_url": "/docs",
        "redoc_url": "/redoc",
        "features": [
            "用户认证和授权",
            "用户管理",
            "物品管理",
            "数据库操作",
            "中间件集成",
            "安全防护",
            "性能监控",
            "错误处理",
            "API 文档"
        ],
        "endpoints": {
            "auth": "/api/auth",
            "users": "/api/users",
            "items": "/api/items",
            "health": "/health",
            "metrics": "/metrics"
        }
    }


# 健康检查端点
@app.get(
    "/health",
    summary="健康检查",
    description="检查应用程序和数据库的健康状态",
    response_description="健康状态信息",
    tags=["监控"]
)
async def health_check():
    """
    健康检查端点
    
    检查应用程序和数据库的健康状态。
    
    Returns:
        dict: 健康状态信息
    """
    try:
        # 检查数据库连接
        db_healthy = await check_db_connection()
        
        return {
            "status": "healthy" if db_healthy else "unhealthy",
            "timestamp": logger.bind().opt().record["time"].isoformat() if hasattr(logger.bind().opt(), 'record') else None,
            "version": "1.0.0",
            "database": {
                "status": "connected" if db_healthy else "disconnected",
                "info": await get_db_info() if db_healthy else None
            },
            "services": {
                "api": "running",
                "authentication": "available",
                "database": "connected" if db_healthy else "disconnected"
            }
        }
    except Exception as e:
        logger.error(f"健康检查失败: {e}")
        return {
            "status": "unhealthy",
            "error": str(e),
            "timestamp": None
        }


# 性能指标端点
@app.get(
    "/metrics",
    summary="性能指标",
    description="获取应用程序性能指标和统计信息",
    response_description="性能指标数据",
    tags=["监控"]
)
async def get_metrics(request: Request):
    """
    获取应用程序性能指标
    
    包括请求统计、性能数据、限流信息等。
    
    Args:
        request: HTTP 请求对象
        
    Returns:
        dict: 性能指标数据
    """
    try:
        metrics = {}
        
        # 获取性能中间件指标
        for middleware in app.user_middleware:
            if hasattr(middleware.cls, 'get_metrics'):
                middleware_name = middleware.cls.__name__
                try:
                    middleware_metrics = middleware.cls.get_metrics()
                    metrics[middleware_name] = middleware_metrics
                except Exception as e:
                    logger.warning(f"获取 {middleware_name} 指标失败: {e}")
                    metrics[middleware_name] = {"error": str(e)}
        
        # 获取限流统计
        for middleware in app.user_middleware:
            if hasattr(middleware.cls, 'get_statistics'):
                middleware_name = middleware.cls.__name__
                try:
                    stats = middleware.cls.get_statistics()
                    if middleware_name not in metrics:
                        metrics[middleware_name] = {}
                    metrics[middleware_name].update({"statistics": stats})
                except Exception as e:
                    logger.warning(f"获取 {middleware_name} 统计失败: {e}")
        
        return {
            "timestamp": logger.bind().opt().record["time"].isoformat() if hasattr(logger.bind().opt(), 'record') else None,
            "application": {
                "name": "FastAPI 学习项目",
                "version": "1.0.0",
                "status": "running"
            },
            "middleware_metrics": metrics
        }
        
    except Exception as e:
        logger.error(f"获取性能指标失败: {e}")
        return {
            "error": "无法获取性能指标",
            "details": str(e)
        }


# 自定义异常处理器
@app.exception_handler(404)
async def not_found_handler(request: Request, exc):
    """
    404 错误处理器
    
    Args:
        request: HTTP 请求对象
        exc: 异常对象
        
    Returns:
        JSONResponse: 404 错误响应
    """
    return JSONResponse(
        status_code=404,
        content={
            "error": "Not Found",
            "message": "请求的资源不存在",
            "path": str(request.url.path),
            "method": request.method,
            "suggestions": [
                "检查 URL 拼写是否正确",
                "查看 API 文档: /docs",
                "访问根路径: /"
            ]
        }
    )


@app.exception_handler(500)
async def internal_server_error_handler(request: Request, exc):
    """
    500 错误处理器
    
    Args:
        request: HTTP 请求对象
        exc: 异常对象
        
    Returns:
        JSONResponse: 500 错误响应
    """
    logger.error(f"内部服务器错误: {exc}")
    return JSONResponse(
        status_code=500,
        content={
            "error": "Internal Server Error",
            "message": "服务器内部错误，请稍后重试",
            "path": str(request.url.path),
            "method": request.method
        }
    )


if __name__ == "__main__":
    """
    直接运行此文件时启动开发服务器
    
    生产环境建议使用:
    uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
    """
    logger.info("🚀 启动 FastAPI 开发服务器...")
    
    uvicorn.run(
        "main:app",
        host="127.0.0.1",
        port=8000,
        reload=True,  # 开发模式，代码变更时自动重载
        log_level="info",
        access_log=True,
        use_colors=True,
        reload_dirs=["."],  # 监控当前目录
        reload_excludes=["*.log", "__pycache__", "*.pyc"]
    )